import LevelBaseControl from "../LevelCommon/LevelBaseControl";
import Stack from "../../utils/Stack";
import CameraMoveStack from "./CameraMoveStack";
import GameConfig from "../../GameConfig";
import EnumData from "../../Enum/EnumData";
import GamePanel from "../Panel/GamePanel";
import LevelObjBase from "../LevelCommon/LevelObjBase";
import RoomControl from "../LevelCommon/RoomControl";
import EventNameList from "../../constant/EventNameList";
import CommonConstant from "../../constant/CommonConstant";
import { utils } from "../../utils/CommonUtil";

export default class CameraControl extends Laya.Script3D {

    private currentScene3D: Laya.Scene3D;

    private currentGamePanel: GamePanel;

    private _mowner: Laya.Sprite3D;
    /** 相机*/
    public _camera: Laya.Camera;

    /** 当前的关卡*/
    private curLevelControl: LevelBaseControl;

    /** 当前的y旋转角度*/
    public curRoateY: number = 0;

    //#region 旋转 控制旋转节点
    /** 控制旋转  x速度要到达的值（鼠标拖动速度）*/
    public mouseConsoleRotateXOff: number = 1;

    /** 控制旋转 x速度要到达的值（手指拖动的速度）*/
    public touchConsoleRotateXOff: number = 35;

    /** 当前操作是否已经生效 旋转*/
    private isEffectRotate: boolean = false;

    /** 当前是否正在旋转相机*/
    //[HideInInspector]
    public isRotateCamera: boolean = false;

    // #endregion

    //#region 缩放 控制缩放节点
    /** 控制缩放的节点*/
    private zoomRoot: Laya.Transform3D;

    /** 相机控制靠近的节点初始位置*/
    private zoomRootOriginPos: Laya.Vector3;

    /** 相机拉近拉远 速度移动端 (最大距离的多少倍)*/
    public zoomCameraSpeed_finger: number = 0.5;

    /** 相机拉近拉远 速度pc (最大距离的多少倍）*/
    public zoomCameraSpeed_pc: number = 20;

    /** 相机最大拉近距离*/
    private zoomCameraMaxDis: number;

    /** 之前的两指距离*/
    private lastFingerDis: number = Number.MIN_VALUE;

    private isMovingCamera: boolean = false;

    //#endregion

    //#region 移动 到某个位置 （直接移动相机本身）
    /** 当前相机的移动栈*/
    //[HideInInspector]
    public curMoveStack: Stack<CameraMoveStack> = new Stack<CameraMoveStack>();
    /** 相机移动tween*/

    private curCameraMoveTween: Laya.Tween;

    //上次记录的两个触模点之间距离
    private lastDistance: number = 0;

    private lastMoveX: number = 0;

    private originalfieldOfView: number;

    private currentfieldOfView: number;

    //收缩的最大FieldOfView为24
    private deltaFieldOfView = 21;

    //单词收缩为8
    private onceDeltaFieldOfView = 7;

    //#endregion

    public set CurLevelControl(value: LevelBaseControl) {
        this.curLevelControl = value;
    }

    onEnable() {
        this.InitComponent();
        this.InitMouseEvent();
    }

    public get MainCamera(): Laya.Camera {
        return this._camera;
    }

    private InitComponent(): void {
        this.currentGamePanel = window.gameFacade.SceneMng.GetPanelById(EnumData.EnumPanelType.GamePanel) as GamePanel;
        if (this.currentGamePanel != null) {
            this.currentScene3D = this.currentGamePanel.CurrentScene3D;
        }

        this._mowner = this.owner as Laya.Sprite3D;
        this._camera = this._mowner.getChildAt(0).getChildByName("Main Camera") as Laya.Camera;
        
        this.initFieldOfView();
        /** 根据参考宽 和当前分辨率的款  算出对应进行旋转时候的 操作x轴速度*/
        this.mouseConsoleRotateXOff = this.mouseConsoleRotateXOff * (Laya.Browser.clientWidth / GameConfig.width);
        this.touchConsoleRotateXOff = this.touchConsoleRotateXOff * (Laya.Browser.clientWidth / GameConfig.width);
        this.zoomRoot = (this.owner.getChildByName("controlZoom") as Laya.Sprite3D).transform;

        this.BloomEff();
    }

    private initFieldOfView() {
        let initRate = GameConfig.width / GameConfig.height;
        let screenRate = Laya.Browser.clientWidth / Laya.Browser.clientHeight;
        let field = 53.6;
        this._camera.fieldOfView = field * (initRate / screenRate);
        this.originalfieldOfView = this.currentfieldOfView = this._camera.fieldOfView;
        console.log("this.originalfieldOfView:" + this.originalfieldOfView);
    }

    //增加后期处理泛光效果
    private BloomEff() {
        var postProcess = new Laya.PostProcess();
        var bloom = new Laya.BloomEffect();
        bloom.intensity = 5;
        bloom.threshold = 0.90;
        bloom.softKnee = 0.5;
        bloom.clamp = 65472;
        bloom.diffusion = 5;
        bloom.anamorphicRatio = 0.0;
        bloom.color = new Laya.Color(1, 1, 1, 1);
        bloom.fastMode = true;
        postProcess.addEffect(bloom);
        this._camera.postProcess = postProcess;
    }

    /** 设置位置信息 参数分别为控制旋转的节点 和控制缩放节点的位置*/
    public SetPosData(rotatePos: Laya.Transform3D, zoomPos: Laya.Transform3D, zoomMaxDis: number) {
        this._mowner.transform.position = rotatePos.position;
        this.zoomRoot.localPosition = zoomPos.localPosition;
        this.zoomRoot.localRotation = zoomPos.localRotation;
        this.zoomRootOriginPos = this.zoomRoot.localPosition.clone();
        this.zoomCameraMaxDis = zoomMaxDis;
    }

    /** 相机是否正在移动*/
    public IsMovingCamera(): boolean {
        return this.isMovingCamera;
    }

    /** 相机移动效果 切换房间的时候 会用*/
    public DoMoveEff(cameraMoveEff: EnumData.CameraMoveEff): void {
        switch (cameraMoveEff) {
            case EnumData.CameraMoveEff.None:
                break;
            case EnumData.CameraMoveEff.LeftToRight:
                this._camera.transform.localPosition = new Laya.Vector3(-3, 0, 0);
                this.isMovingCamera = true;
                utils.CommonUtils.DOPositionTween(
                    this._camera.transform,
                    this._camera.transform.localPosition,
                    new Laya.Vector3(0, 0, 0)
                ,1000, Laya.Handler.create(this, () => {
                    this.isMovingCamera = false;
                }),true)
                // this.curCameraMoveTween = Laya.Tween.to(
                //     this._camera.transform,
                //     { localPosition: new Laya.Vector3(0, 0, 0) },
                //     1000,
                //     null,
                //     Laya.Handler.create(this, () => {
                //         this.isMovingCamera = false;
                //     }))
                break;
            case EnumData.CameraMoveEff.RightToLeft:
                this._camera.transform.localPosition = new Laya.Vector3(3, 0, 0);
                this.isMovingCamera = true;

                utils.CommonUtils.DOPositionTween(
                    this._camera.transform,
                    this._camera.transform.localPosition,
                    new Laya.Vector3(0, 0, 0)
                ,500, Laya.Handler.create(this, () => {
                    this.isMovingCamera = false;
                }),true)

                // this.curCameraMoveTween = Laya.Tween.to(
                //     this._camera.transform,
                //     { localPosition: new Laya.Vector3(0, 0, 0) },
                //     1000,
                //     null,
                //     Laya.Handler.create(this, () => {
                //         this.isMovingCamera = false;
                //     })
                // )
                break;
            default:
                break;
        }
    }

    private InitMouseEvent() {
        this.currentGamePanel.cameraTouchImage.displayObject.on(Laya.Event.MOUSE_DOWN, this, this.MouseHandler);
        this.currentGamePanel.cameraTouchImage.displayObject.on(Laya.Event.MOUSE_UP, this, this.MouseHandler);
        this.currentGamePanel.cameraTouchImage.displayObject.on(Laya.Event.MOUSE_OUT, this, this.MouseHandler);
        this.currentGamePanel.cameraTouchImage.displayObject.on(Laya.Event.MOUSE_WHEEL, this, this.MouseHandler);
    }

    onDisable() {
        this.currentGamePanel.cameraTouchImage.displayObject.off(Laya.Event.MOUSE_DOWN, this, this.MouseHandler);
        this.currentGamePanel.cameraTouchImage.displayObject.off(Laya.Event.MOUSE_UP, this, this.MouseHandler);
        this.currentGamePanel.cameraTouchImage.displayObject.off(Laya.Event.MOUSE_MOVE, this, this.MouseHandler);
        this.currentGamePanel.cameraTouchImage.displayObject.off(Laya.Event.MOUSE_OUT, this, this.MouseHandler);
        this.currentGamePanel.cameraTouchImage.displayObject.off(Laya.Event.MOUSE_WHEEL, this, this.MouseHandler);
    }

    private MouseHandler(e: Laya.Event) {
        var touches: Array<any> = e.touches;

        switch (e.type) {
            case Laya.Event.MOUSE_DOWN:
                {
                    if (touches && touches.length == 2) {
                        this.lastDistance = this.getDistance(touches);
                    }

                    if (touches && touches.length == 1) {
                        this.lastMoveX = touches[0].stageX;
                    }else{
                        this.lastMoveX = e.stageX;
                    }

                    this.currentGamePanel.cameraTouchImage.displayObject.on(Laya.Event.MOUSE_MOVE, this, this.MouseHandler);
                    break;
                }
            case Laya.Event.MOUSE_MOVE:
                {
                    if (touches && touches.length == 2) {
                        var distance: number = this.getDistance(e.touches);

                        let delta = distance - this.lastDistance;
                        if (Math.abs(delta) > 10) {
                            this.ZoomCamera(distance - this.lastDistance);
                        }

                        break;
                    }

                    if (touches && touches.length == 1) {
                        let currentX = touches[0].stageX;
                        let delta = this.lastMoveX - currentX;
                        if (Math.abs(delta) > 20) {
                            this.RotateCamera(delta);
                        }
                    }else{
                        let currentX = e.stageX;
                        let delta = this.lastMoveX - currentX;
                        if (Math.abs(delta) > 20) {
                            this.RotateCamera(delta);
                        }
                    }

                    break;
                }
            case Laya.Event.MOUSE_OUT:
            case Laya.Event.MOUSE_UP:
                {
                    this.currentGamePanel.cameraTouchImage.displayObject.off(Laya.Event.MOUSE_MOVE, this, this.MouseHandler);
                    break;
                }
        }
    }

    /**计算两个触摸点之间的距离*/
    private getDistance(points: Array<any>): number {
        var distance: number = 0;
        if (points && points.length == 2) {
            var dx: number = points[0].stageX - points[1].stageX;
            var dy: number = points[0].stageY - points[1].stageY;

            distance = Math.sqrt(dx * dx + dy * dy);
        }
        return distance;
    }

    /** 限制相机超过*/
    /** 旋转相机*/
    private RotateCamera(xSpeed: number): void {
        if (this.isRotateCamera || this.curMoveStack.Count > 0 || this.IsMovingCamera()) {
            return;
        }
        if (xSpeed > 0) {
            /** y轴旋转*/
            this.curRoateY += 90;
        }
        else {
            /** y轴旋转*/
            this.curRoateY -= 90;
        }

        /** 开始旋转相机*/
        this.isRotateCamera = true;
        /** 如果是房间 改变墙*/
        let curLevelObjBase: LevelObjBase = this.curLevelControl.GetCurLevelObj();
        if (curLevelObjBase instanceof RoomControl) {
            let roomControl: RoomControl = curLevelObjBase as RoomControl;
            roomControl.ChangeWall();
        }

        Laya.Tween.to((this.owner as Laya.Sprite3D).transform, { localRotationEulerY: this.curRoateY }, 1000, null, Laya.Handler.create(this, () => {
            this.isRotateCamera = false;
        }));
    }

    /** 缩放相机 根据参数 两指变化距离*/
    private ZoomCamera(changeDis: number): void {
        console.log("this._camera.fieldOfView" + this._camera.fieldOfView);
        if (this.isRotateCamera || this.curMoveStack.Count > 0 || this.IsMovingCamera()) {
            return;
        }

        //当前的距离小于上次距离，说明在收缩，应该变远
        if (changeDis < 0) {

            if (this.currentfieldOfView >= this.originalfieldOfView) {//已经最远了
                return
            }

            let targtFieldOfView = Math.min(this.currentfieldOfView + this.onceDeltaFieldOfView, this.originalfieldOfView);
            this.isRotateCamera = true;
            Laya.Tween.to(this._camera, { fieldOfView: targtFieldOfView }, 1000, null, Laya.Handler.create(this, () => {
                this.currentfieldOfView = targtFieldOfView;
                this.isRotateCamera = false;
            }));

        } else {//应该拉进

            if (this.currentfieldOfView <= (this.originalfieldOfView - this.deltaFieldOfView)) {//已经最近了
                return
            }

            let targtFieldOfView = Math.max(this.currentfieldOfView - this.onceDeltaFieldOfView, this.originalfieldOfView - this.deltaFieldOfView);
            this.isRotateCamera = true;
            Laya.Tween.to(this._camera, { fieldOfView: targtFieldOfView }, 1000, null, Laya.Handler.create(this, () => {
                this.currentfieldOfView = targtFieldOfView;
                this.isRotateCamera = false;

                console.log("fieldOfView" + this._camera.fieldOfView);
            }));
        }
    }

    /** 移动相机到指定位置 和旋转 返回时否可以入栈相机  如果不是父子关系的物体触发的 不入栈 比如你聚焦了一个柜子上 柜子旁边有个桌子也有聚焦操作 这时候应该避免点击到桌子 进行聚焦*/
    public PushMoveStack(moveStack: CameraMoveStack): boolean {
        /** 相机旋转的时候 不移动*/
        if (this.isRotateCamera)
            return false;
        if (this.curMoveStack.Count > 0) {
            let lastStack: CameraMoveStack = this.curMoveStack.Peek();
            /** 不是父子关系的物体 不聚焦*/
            if (lastStack.curInteractObj != moveStack.curInteractObj.parentInteractive) {
                return false;
            }
        }

        /** 移动相机速度*/
        let moveTime: number = moveStack.moveTime;
        let targetPos: Laya.Transform3D = moveStack.targetPos;

        this.isMovingCamera = true;

        utils.CommonUtils.DOPositionTween(
            this._camera.transform,
            this._camera.transform.position.clone(),
            targetPos.position,
            moveTime,
            null,
            false
        );

        utils.CommonUtils.DORotateTween(
            this._camera.transform,
            this._camera.transform.rotationEuler.clone(),
            targetPos.rotationEuler,
            moveTime,
            Laya.Handler.create(this,()=>{
                this.isMovingCamera = false;
            }),false);
       
        this.curMoveStack.Push(moveStack);//摄像机入栈了
        console.log("摄像机入栈了:", moveStack);
        window.gameFacade.EventMng.dispatch(EventNameList.RefreshBackCameraBtn);//触发返回按钮激活事件
        return true;
    }

    /** 相机移动出栈  当摄像机聚焦物体后点返回按钮返回*/
    public PopMoveStack(): void {
        if (this.curMoveStack.Count == 0) {
            return;
        }
        else {
            /**出栈 当前栈顶*/
            let curPopMove: CameraMoveStack = this.curMoveStack.Pop();
            /** 移动相机速度*/
            let moveTime = curPopMove.moveTime;
            /** 执行出栈回调逻辑*/
            curPopMove.PopStack(this.owner);

            if (this.curMoveStack.Count == 0) {
                /** 栈中没有位置信息了 相机归位*/
                this.isMovingCamera = true;

                utils.CommonUtils.DOPositionTween(
                    this._camera.transform,
                    this._camera.transform.localPosition.clone(),
                    new Laya.Vector3(0,0,0),
                    moveTime,
                    null,
                    true
                );

                utils.CommonUtils.DORotateTween(
                    this._camera.transform,
                    this._camera.transform.localRotationEuler.clone(),
                    new Laya.Vector3(0, 0, 0),
                    moveTime,
                    Laya.Handler.create(this,()=>{
                        window.gameFacade.EventMng.dispatch(EventNameList.CameraResetPosEvent);
                        this.isMovingCamera = false;
                    }),true);
            }
            else {
                /** 上一个栈目标位置*/
                let targetPos: Laya.Transform3D = this.curMoveStack.Peek().targetPos;
                this.isMovingCamera = true;

                utils.CommonUtils.DOPositionTween(
                    this._camera.transform,
                    this._camera.transform.position.clone(),
                    targetPos.position,
                    moveTime,
                    null,
                    false
                );

                utils.CommonUtils.DORotateTween(
                    this._camera.transform,
                    this._camera.transform.rotationEuler.clone(),
                    targetPos.rotationEuler,
                    moveTime,
                    Laya.Handler.create(this,()=>{
                        this.isMovingCamera = false;
                    }),false);
            }
        }
    }
}